package com.example.springsecurity.security;

import com.example.springsecurity.annotation.Anonymous;
import lombok.Data;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.PathPatternsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author wuancheng
 * @date 2024/6/19 16:56
 * @description 收集匿名访问路径
 */
@Data
@Configuration
public class AnonymousAccessUrl implements InitializingBean {

    @Resource
    private ApplicationContext applicationContext;

    private List<String> urls = new ArrayList<>();

    /**
     * 在 Spring 容器完成对 bean 的属性设置后，执行自定义的初始化逻辑
     * 这里主要收集可以匿名访问的方法路径
     *
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() {
        // 获取所有@RequestMapping的方法
        RequestMappingHandlerMapping mappingHandlerMapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
        Map<RequestMappingInfo, HandlerMethod> handlerMethodsMap = mappingHandlerMapping.getHandlerMethods();

        handlerMethodsMap.keySet().stream().forEach(methodKey -> {
            HandlerMethod handlerMethod = handlerMethodsMap.get(methodKey);
            Anonymous anonymous = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class);
            // 检查方法上的 @Anonymous 注解
            if (anonymous != null) {
                PathPatternsRequestCondition condition = methodKey.getPathPatternsCondition();
                Optional.ofNullable(methodKey.getPathPatternsCondition())
                        .map(pathPatternsCondition -> pathPatternsCondition.getPatterns())
                        .ifPresent(patternsSet -> patternsSet.forEach(patterns -> urls.add(patterns.getPatternString())));
            }
        });
    }
}
